package com.yc.bestMatching;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;

/***
 * 线程池的任务分配及调度 结果汇总
 */
public class BestMatchingConcurrentCalculation {
    public static BestMatchingData getBestMatchingWords(String word, List<String> dictionary) throws InterruptedException, ExecutionException {
        BestMatchingData result=new BestMatchingData();
        // 1.任务数
        int numCores=Runtime.getRuntime().availableProcessors(); //单例模型
        ThreadPoolExecutor executor=(ThreadPoolExecutor) Executors.newFixedThreadPool(numCores);


        // 2.计算每个任务对应的词汇量  startIndex 到 endIndex
        int size=dictionary.size();
        int step=size/numCores;  //任务地分区大小
        int startIndex,enndIndex;

        // 3.创建 BestMatchingTask
        List<BestMatchingTask> tasks=new ArrayList<>();
        for(int i=0;i<numCores;i++){
            startIndex=i*step;
            //endIndex
            if(i==numCores-1){
                enndIndex=size;
            }else {
                enndIndex=(i+1)*step;
            }
            BestMatchingTask task=new BestMatchingTask(dictionary,word,startIndex,enndIndex);
            tasks.add(task);
        }

        // 4.将上面创建的BestMatchingTask 提交给  Executor线程池执行器运行
        //invokeAll()一次性提交任务后 只有所有的任务执行完毕后 才会向下执行
        //换句话说 即程序会阻塞此处
        List<Future<BestMatchingData>> listFuture= executor.invokeAll( tasks  ); //一次性提交所有任务
        System.out.println("如果任务没有完成 invokeAll阻塞此处");
        executor.shutdown(); //因为任务完成了 所以关闭执行器

        // 5.通过FutureTask.get() 获取以上任务地执行结果 BestMatchingData 汇总（找最小距离 及 对应的词汇表
        int minDistance=Integer.MAX_VALUE;
        List<String> words=new ArrayList<>(); //最短距离 对应的单词
        for(Future<BestMatchingData> future:listFuture){
            BestMatchingData bestMatchingData=future.get();
            if(bestMatchingData.getDistance()<minDistance){
                words.clear();
                minDistance= bestMatchingData.getDistance();
                words.addAll(bestMatchingData.getWords());
            } else if (bestMatchingData.getDistance()==minDistance) {
                //这个任务找到最短距离 与已知的一样 则合并单词列表
                words.addAll(bestMatchingData.getWords());
            }
        }

        // 6.包装成BestMatchingData
        result.setDistance(minDistance);
        result.setWords(words);
        return result;
    }
}









